package tankproject;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;

//class PaintTask extends TimerTask {
//}
//Use this for the bullet animation. Need mouse input for the rest of the bullet configuration
abstract class Vehicle {
}

class Turret extends JPanel implements MouseMotionListener {
    private Tank tank = null;
    
    private double turretA;
    private double my;
    private double mx;
    
    public double turretAngle () {
        double temp= 0;
         double a = (Math.atan2(tank.getPositionx() - (double) my, tank.getPositiony() - (double) mx));
         
         if (a > 0 && a < Math.PI/2) {
                temp = a + (3*Math.PI/2);
            } else if (a > Math.PI/2 && a < Math.PI) {
                temp = a - (Math.PI/2);
            } else if (a < 0 && a > -Math.PI/2) {
                temp = Math.PI + ((Math.PI/2) - Math.abs(a));
            } else if (a < -Math.PI/2 && a > -Math.PI) {
                temp = (Math.PI/2) + (Math.PI - Math.abs(a));
            } else if (a == 0) {
                temp = 3*Math.PI/2;
            } else if (a == Math.PI/2) {
                temp = 0;
            } else if (a == Math.PI || a == -Math.PI) {
                temp = Math.PI/2;
            } else if (a == -Math.PI/2) {
                temp = Math.PI;
            }
         return temp;
    }
            
    @Override
    public void mouseDragged(MouseEvent e) {
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        this.setMy(e.getY());
        this.setMx(e.getX());
    }


    /**
     * @return the my
     */
    public double getMy() {
        return my;
    }
    
     /**
     * @param my the my to set
     */
    public void setMy(double my) {
        this.my = my;
    }

    /**
     * @return the mx
     */
    public double getMx() {
        return mx;
    }

    /**
     * @param mx the mx to set
     */
    public void setMx(double mx) {
        this.mx = mx;
    }

    /**
     * @return the turretA
     */
    public double getTurretA() {
        turretA = turretAngle();
        setTurretA(turretA);
        return turretA;
    }

    /**
     * @param turretA the turretA to set
     */
    public void setTurretA(double turretA) {
        this.turretA = turretA;
    }
}

class Tank extends JPanel {

    private double positionx = 300;
    private double positiony = 300;
    
    private double xRate = 0;
    private double yRate = 0;
    
    private double fuel = 500;
    private double speed = 0;
    private double bullets = 50;
    private double maxSpeed = 80;
    private double minSpeed = 0;
    private double fuelMax = 500;
    private double fuelMin = 0;
    private double maxBullets = 50;
    private double minBullets = 0;
    private double angle = 0;

    public double getFuel() {
        return fuel;
    }

    public void setFuel(double fuel) {
        this.fuel = fuel;
    }

    public double getSpeed() {
        return speed;
    }

    public void setSpeed(double speed) {
        this.speed = speed;
    }

    public double getBullets() {
        return bullets;
    }

    public void setBullets(double bullets) {
        this.bullets = bullets;
    }

    public double getMaxSpeed() {
        return maxSpeed;
    }

    public void setMaxSpeed(double maxSpeed) {
        this.maxSpeed = maxSpeed;
    }

    public double getMinSpeed() {
        return minSpeed;
    }

    public void setMinSpeed(double minSpeed) {
        this.minSpeed = minSpeed;
    }

    public double getFuelMax() {
        return fuelMax;
    }

    public void setFuelMax(double fuelMax) {
        this.fuelMax = fuelMax;
    }

    public double getFuelMin() {
        return fuelMin;
    }

    public void setFuelMin(double fuelMin) {
        this.fuelMin = fuelMin;
    }

    public double getMaxBullets() {
        return maxBullets;
    }

    public void setMaxBullets(double maxBullets) {
        this.maxBullets = maxBullets;
    }

    public double getMinBullets() {
        return minBullets;
    }

    public void setMinBullets(double minBullets) {
        this.minBullets = minBullets;
    }

    public double getPositionx() {
        return positionx;
    }

    public void setPositionx(double positionx) {
        this.positionx = positionx;
    }

    public double getPositiony() {
        return positiony;
    }

    public void setPositiony(double positiony) {
        this.positiony = positiony;
    }

    public double getAngle() {
        return angle;
    }

    public void setAngle(double angle) {
        this.angle = angle;
    }

    /**
     * @return the xRate
     */
    public double getxRate() {
        return xRate;
    }

    /**
     * @param xRate the xRate to set
     */
    public void setxRate(double xRate) {
        this.xRate = xRate;
    }

    /**
     * @return the yRate
     */
    public double getyRate() {
        return yRate;
    }

    /**
     * @param yRate the yRate to set
     */
    public void setyRate(double yRate) {
        this.yRate = yRate;
    }
}

class TankView extends JPanel {
    
    Turret turret = new Turret();
    private Tank tank = null;

    private TankView() {
    }

    public TankView(Tank model) {
        this.tank = model;
    }
    public void update() {
        //update the base x, y and angle
        //update the turret x, y and the angle given my the mousefollower
        //bullet x, y angle will be constant when it is released
        
//        tank.setxRate(Math.toRadians(11));
//        tank.setyRate(Math.toRadians(11));
        
        
        //we need the change in x
        //we need the change in y
        
       tank.setPositionx(tank.getPositionx() + tank.getxRate() * tank.getSpeed()); //THIS IS WHAT WE ACTUALLY NEED TO USE
        tank.setPositiony(tank.getPositiony() + tank.getyRate() * tank.getSpeed()); //THIS IS WHAT WE ACTUALLY NEED TO USE
       // tank.setPositionx(tank.getPositionx() + tank.getxRate());
        
        System.out.println(tank.getxRate() + "is the xRate");
        //tank.setPositiony(tank.getPositiony() + tank.getyRate());
        System.out.println(tank.getyRate() + "is the yRate");
        
        
        
        //turret.getPositionx(); // will be relative to the tank position
        //turret.getPositiony(); // will be relative to the tank position
        //bullet.getPositionx(); //will be initialized at turret position, but then no longer be tied to the turret.
        //bullet.getPositiony();
        
    }

    @Override
    public void paint(Graphics g) {
        
        update();
        Rectangle rect = this.getBounds();
        AffineTransform af = new AffineTransform();
        Graphics2D g2 = (Graphics2D) g;
        Graphics2D g3 = (Graphics2D) g;
        Image img = Toolkit.getDefaultToolkit().getImage("./tank.png");
        int imgW = img.getWidth(this);
        int imgH = img.getHeight(this);
        Image background = Toolkit.getDefaultToolkit().getImage("./paper.jpg");
        Image img2 = Toolkit.getDefaultToolkit().getImage("./tankcannon.png");
        g2.setColor(Color.white);
        //g2.fillRect(0, 0, 800, 600);
        g2.drawImage(background, 0, 0, this);
        g2.setColor(Color.black);
        g2.drawString("xrate: " + tank.getxRate(), 10, 10);
        g2.drawString("yrate: " + tank.getyRate(), 10, 20);
        g2.translate(tank.getPositionx(), tank.getPositiony());
        g2.rotate(Math.toRadians(tank.getAngle()), imgW / 2, imgH / 2);
        g2.drawImage(img, 0, 0, this);
        g3.translate(imgW/3, 0);
        //g3.rotate(turret.getTurretA(), 0, 0);
        g3.drawImage(img2, 0, 0, this);
        
        
        
        
        try {
            Thread.sleep(100);
        } catch (InterruptedException ex) {
            Logger.getLogger(TankView.class.getName()).log(Level.SEVERE, null, ex);
        }
        repaint();
        
    }
}

class TankController implements MouseListener, KeyListener, MouseMotionListener, FocusListener {

    private TankView view = null;
    private Tank tank = null;

    private TankController() {
        
    }

    public TankController(Tank model, TankView view) {
        this.view = view;
        this.tank = model;
    }

    public TankView getView() {
        return view;
    }

    public void setView(TankView view) {
        this.view = view;
    }

    public Tank getTank() {
        return tank;
    }

    public void setTank(Tank tank) {
        this.tank = tank;
    }

    public void doSpeedUp() {
        if (tank.getSpeed() < 80) {
            tank.setSpeed(tank.getSpeed() + 20);
        }
    }

    public void doSlowDown() {
        if (tank.getSpeed() > 0) {
            tank.setSpeed(tank.getSpeed() - 20);
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    public double xAngle(double x, double s) {
        return s * Math.cos(x);
    }

    public double yAngle(double y, double s) {
        return s * Math.sin(y);
    }

    @Override
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();  // Keyboard code for the pressed key.
        double px = 0, py = 0;

        if (key == KeyEvent.VK_UP || key == KeyEvent.VK_W) {

            
//            double tempY = tank.getPositiony();
//            double tempX = tank.getPositionx();
//            double temp2 = tank.getAngle();
//            double temp3;
//            double temp4;
            doSpeedUp();
            //if (tank.getSpeed() < 80) {
            //    temp4 = tank.getSpeed();
            //   temp4 += 20;
            //   tank.setSpeed(temp4);
            //}

//            if (temp2 > 0 && temp2 < 90) {
//                temp3 = 90 - temp2;
//                temp3 = Math.toRadians(temp3);
//                px = xAngle(temp3, tank.getSpeed());
//                py = -yAngle(temp3, tank.getSpeed());
//            } else if (temp2 > 90 && temp2 < 180) {
//                temp3 = temp2 - 90;
//                temp3 = Math.toRadians(temp3);
//                px = xAngle(temp3, tank.getSpeed());
//                py = yAngle(temp3, tank.getSpeed());
//            } else if (temp2 > 180 && temp2 < 270) {
//                temp3 = 270 - temp2;
//                temp3 = Math.toRadians(temp3);
//                px = -xAngle(temp3, tank.getSpeed());
//                py = yAngle(temp3, tank.getSpeed());
//            } else if (temp2 > 270 && temp2 < 360) {
//                temp3 = temp2 - 270;
//                temp3 = Math.toRadians(temp3);
//                px = -xAngle(temp3, tank.getSpeed());
//                py = -yAngle(temp3, tank.getSpeed());
//            } else if (temp2 == 0 || temp2 == 360) {
//                px = 0;
//                py = -tank.getSpeed();
//            } else if (temp2 == 270) {
//                px = -tank.getSpeed();
//                py = 0;
//            } else if (temp2 == 180) {
//                px = 0;
//                py = tank.getSpeed();
//            } else if (temp2 == 90) {
//                px = tank.getSpeed();
//                py = 0;
//            }
//
//                py += tempY;
//                px += tempX;
//                
//                if (px < 0 || px > 725 || py < 0 || py >475) {
//                    System.out.println("YOU MUST STAY WITHIN THE BOUDARIES!!!");
//                    //tank.setSpeed(0);
//                } else {
//                
//                tank.setPositiony(py);
//                tank.setPositionx(px);
//
//                System.out.println(tank.getAngle());
//                System.out.println("x: " + px + " y: " + py);
//                
//            } 
        }
        if (key == KeyEvent.VK_DOWN || key == KeyEvent.VK_S) {
            doSlowDown();
            System.out.println(tank.getAngle());
        }

        if (key == KeyEvent.VK_LEFT || key == KeyEvent.VK_A) {
            double temp = tank.getAngle();
            temp -= 10;
            if (temp < 0) {
                temp += 360;
            }
            tank.setAngle(temp);
        }
        if (key == KeyEvent.VK_RIGHT || key == KeyEvent.VK_D) {
            double temp = tank.getAngle();
            temp += 10;
            if (temp > 360) {
                temp -= 360;
            }
            tank.setAngle(temp);
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

    @Override
    public void mouseDragged(MouseEvent e) {
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        this.view.requestFocus();
        this.view.repaint();
    }

    @Override
    public void focusGained(FocusEvent e) {
    }

    @Override
    public void focusLost(FocusEvent e) {
    }
    
    public void move() {
        
//        while (px < 0 || px > 725 || py < 0 || py >475) {
//                  System.out.println("YOU MUST STAY WITHIN THE BOUDARIES!!!");
//        if (px < 0) {
//            tank.setSpeed(0);
//        } else if (px > 725) {
//            
//        } else if(py < 0) {
//            
//        } else if (py > 475) {
//            
//        }
        
        
        
        
        tank.setPositionx(tank.getPositionx() - (tank.getSpeed() * Math.cos(tank.getAngle())));
        tank.setPositiony(tank.getPositiony() - (tank.getSpeed() * Math.sin(tank.getAngle())));
    
    
    }
    
}

class PaintTask extends TimerTask {
    TankView view = null;
    TankController controller = null;
    
    PaintTask(TankView view, TankController controller) {
        this.view = view;
        this.controller = controller;
    }

    @Override
    public void run() {
        controller.move();
        view.repaint();
    }
}

public class TankProject {

    public static void main(String[] args) {

        Tank tank = new Tank();
        TankView view = new TankView(tank);
        TankController controller = new TankController(tank, view);
        PaintTask paintTask = new PaintTask(view, controller);

        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());
        mainPanel.add(view, BorderLayout.CENTER);

        JFrame f = new JFrame();
        f.setSize(new Dimension(800, 600));
        f.setTitle("Tank Project");
        f.setContentPane(mainPanel);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
        f.addKeyListener(controller);

        Timer t = new Timer();
        //t.scheduleAtFixedRate(paintTask, delay in ms, period);
        t.scheduleAtFixedRate(paintTask, 0, 25);
        
        
        
        
    }
}
